﻿#region

using System;
using System.Linq;
using System.Reflection;
using JsMapper.BO.Attributes;
using JsMapper.BO.Config;
using JsMapper.BO.Events;

#endregion

namespace JsMapper.BL.Config
{
    public class JsModelConfigManager
    {
        private JsModelConfig _config;

        public JsModelConfig Config
        {
            get
            {
                if (_config == null) throw new NullReferenceException("Config must be initialised!");
                return _config;
            }
            set
            {
                _config = value;
                InitializeConfig();
            }
        }

        public void Configurate(JsModelConfig config)
        {
            Config = config;
        }

        public event JsModelCollectionHandler OnCollection;
        public event JsModelCacheHandler OnUseCache;

        public static bool IsConfigured { get; private set; }

        private void InitializeConfig()
        {
            if (Config.UseCache) UseCache();
            if (Config.ScanJsModelsFromCurrentDomain) ScanJsModels();
            if (!string.IsNullOrEmpty(Config.ScanJsModelsFromAssembly)) ScanJsModels(Config.ScanJsModelsFromAssembly);

            IsConfigured = true;
        }

        private void ScanJsModels()
        {
            if (OnCollection == null) throw new NullReferenceException("No handler for the scanned Models");

            var coll = AppDomain.CurrentDomain.GetAssemblies()
                                .SelectMany(assmbls => assmbls.GetTypes(), (a, t) => t)
                                .Where(x => Attribute.IsDefined(x, typeof (JsModelAttribute)))
                                .ToList();


            var collArgs = new JsModelCollectionEventArgs(coll);
            OnCollection(this, collArgs);
        }

        private void ScanJsModels(string assemblyFile)
        {
            if (OnCollection == null) throw new NullReferenceException("No handler for the scanned Models");

            var selectedAssembly = Assembly.LoadFrom(assemblyFile);
            var coll = selectedAssembly.GetTypes()
                                       .Where(x => Attribute.IsDefined(x, typeof (JsModelAttribute)))
                                       .ToList();

            var collArgs = new JsModelCollectionEventArgs(coll);
            OnCollection(this, collArgs);
        }

        private void UseCache()
        {
            if (OnUseCache == null) return;

            var cacheArgs = new JsModelCacheEventArgs();
            OnUseCache(this, cacheArgs);
        }
    }
}